#include <iostream>
#include <vector>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include "task.hpp"
#define PIPENUM 10

using namespace std;
class Pipe
{
    public:
    string _name;
    int _wfd;
    pid_t _childId;

    Pipe(string name, int wfd, pid_t childId)
    :_name(name),
    _wfd(wfd),
    _childId(childId)
    {}
};

void run()
{
    while(1)
    {
        int task_code;
        ssize_t n = read(0, &task_code, sizeof(task_code));
        if(n == sizeof(task_code))
        {
            cout << "child:" << getpid() << " get taskcode:" << task_code << endl;
            tasks[task_code]();
            cout << "----------------------------------" << endl;
        }
        if(n == 0)
        {
            cout << "child:" << getpid() << "run ending" << endl;
            break;
        }
    }
}

void initProcessPoll(vector<Pipe> & pipes)
{
    for(int i = 0; i < PIPENUM; i++)
    {
        int pipefd[2];
        int n = pipe(pipefd);
        if(n == -1) return;

        pid_t id = fork();
        if(id == 0)
        {
            //child
            close(pipefd[1]);
            dup2(pipefd[0], 0);
            close(pipefd[0]);
            run();

            exit(0);
        }
        //father
        close(pipefd[0]);
        string name = "child-" + to_string(i);
        pipes.push_back(Pipe(name, pipefd[1], id));
    }

}

void conlChild(const vector<Pipe>& pipes)
{
    int n = 5;
    while(n--)
    {
        //选择任务
        int task_code = rand()%N;
        //选择进程
        int process_code = rand()%PIPENUM;
        //发送任务
        write(pipes[process_code]._wfd, &task_code, sizeof(task_code));
        cout << "task_code:" << task_code << " has been sent to child:" << pipes[process_code]._name << '-' <<pipes[process_code]._childId << endl;
        sleep(1);
    }
}

void quit(vector<Pipe>& pipes)
{
    for(auto& e: pipes){
        close(e._wfd);
    }

    for(auto& e: pipes){
        waitpid(e._childId, nullptr, 0);
    }
}
int main()
{
    srand(time(nullptr));
    vector<Pipe> pipes;
    //init
    initProcessPoll(pipes);

    //Debug
    // for(auto& e:pipes)
    // {
    //     cout << "wfd:" << e._wfd << ' ' << "childId:" << e._childId << ' ' << "name:" << e._name << endl;
    // }

    //control child
    conlChild(pipes);

    //quit
    quit(pipes);
    return 0;
}   